package com.ajaxlord.confluence.plugin.json.actions;

import com.atlassian.confluence.core.ContentPropertyManager;
import com.atlassian.confluence.mail.notification.NotificationManager;
import com.atlassian.confluence.pages.AbstractPage;
import com.atlassian.confluence.pages.Page;
import com.atlassian.confluence.pages.TinyUrl;
import com.atlassian.confluence.renderer.PageContext;
import com.atlassian.core.util.FileSize;
import com.atlassian.renderer.WikiStyleRenderer;
import com.atlassian.user.User;
import org.apache.xml.serialize.HTMLSerializer;
import org.apache.xml.serialize.Method;
import org.apache.xml.serialize.OutputFormat;
import org.cyberneko.html.parsers.DOMParser;
import org.randombits.confluence.support.sorting.NaturalTitleComparator;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.List;

public class PageAction extends AbstractPageAction {
    private ContentPropertyManager contentPropertyManager;
    private NotificationManager notificationManager;

    private List children;
    private String excerpt;

    private User creator;
    private User lastModifier;
    private WikiStyleRenderer wikiStyleRenderer;

    public User getCreator() {
        if (creator == null && getPage() != null) {
            creator = userAccessor.getUser(getPage().getCreatorName());
        }
        return creator;
    }

    public User getLastModifier() {
        if (lastModifier == null && getPage() != null) {
            lastModifier = userAccessor.getUser(getPage().getLastModifierName());
        }
        return lastModifier;
    }

    public String getTinyUrl() {
        TinyUrl tinyUrl = new TinyUrl(getPage());
        return getHelper().getDomainName() + "/x/" + tinyUrl.getIdentifier();
    }

    public void setWikiStyleRenderer(WikiStyleRenderer wikiStyleRenderer) {
        this.wikiStyleRenderer = wikiStyleRenderer;
    }

    public String getXHtmlContent() {
        PageContext context = getPage().toPageContext();
        return wikiStyleRenderer.convertWikiToXHtml(context, getPage().getContent());
    }

    public String getPanels() {
        DOMParser parser = new DOMParser();
        try {
            parser.parse(new InputSource(new StringReader(getXHtmlContent())));
            findPanel(parser.getDocument());
            sb.deleteCharAt(sb.length() - 1);
            sb.append("]");
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return sb.toString();
        }
    }

    public String getTocContent() {
        //TODO
        return null;
    }

    public String getPanelContent() {
        //TODO
        return null;
    }

    public int getAttachmentCount() {
        List attachments = getAttachments();
        if (attachments == null)
            return 0;
        return attachments.size();
    }

    public List getChildren() {
        if (children == null) {
            AbstractPage apage = getPage();
            if (apage instanceof Page) {
                children = removeInvisibleContent(((Page) apage).getChildren());
                Collections.sort(children, new NaturalTitleComparator());
            }
        }
        return children;
    }

    public void setContentPropertyManager(ContentPropertyManager contentPropertyManager) {
        this.contentPropertyManager = contentPropertyManager;
    }

    public String getNiceSourceSize() {
        if (getPage() != null && getPage().getContent() != null) {
            String enc = getGlobalSettings().getDefaultEncoding();
            if (enc == null)
                enc = "UTF-8";
            try {
                int size = getPage().getContent().getBytes(enc).length;
                return FileSize.format(size);
            }
            catch (UnsupportedEncodingException e) {
                return FileSize.format(getPage().getContent().length());
            }
        }
        return FileSize.format(0);
    }

    public StringBuilder sb = new StringBuilder("[");

    public void findPanel(Node node) {
        if (node.getNodeName().equalsIgnoreCase("DIV")) {
            for (int i = 0; i < node.getAttributes().getLength(); i++) {
                if (node.getAttributes().item(i).getNodeName().toLowerCase().equals("class") && node.getAttributes().item(i).getNodeValue().toLowerCase().equals("panel")) {
                    sb.append("{");
                    for (int j = 0; j < node.getChildNodes().getLength(); j++) {
                        NamedNodeMap atts = node.getChildNodes().item(j).getAttributes();
                        for (int k = 0; k < atts.getLength(); k++) {
                            if (atts.item(k).getNodeName().toLowerCase().equals("class") && atts.item(k).getNodeValue().toLowerCase().equals("panelcontent")) {
                                sb.append("\"content\":\"");
                                sb.append(innerHTML(node.getChildNodes().item(j)).replaceAll("'", "\\\\'").replaceAll("\"", "\\\\\"").replaceAll("^<P>", "").replaceAll("$</P>", ""));
                                sb.append("\"");
                            }
                        }
                    }
                    sb.append("},");
                }
            }
        }
        Node child = node.getFirstChild();
        while (child != null) {
            findPanel(child);
            child = child.getNextSibling();
        }
    }


    public String convertNodeToString(Node node) {
        StringWriter sw = new StringWriter();
        OutputFormat format = new OutputFormat(Method.TEXT, null, false);
        HTMLSerializer ds = new HTMLSerializer(sw, format);
        try {
            ds.asDOMSerializer().serialize((org.apache.html.dom.HTMLDivElementImpl) node);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return sw.toString().replaceAll("\\p{Cntrl}", "").replaceAll("<![^>]*>", "");
        }
    }

    public String innerHTML(Node node) {
        String st = convertNodeToString(node);
        int igt = st.indexOf(">");
        int ilt = st.lastIndexOf("<");
        if (igt == -1 || ilt == -1 || igt >= ilt) return st;
        return st.substring(igt + 1, ilt).trim();
    }
}
